package newcrunch.typography;

import java.awt.Color;
import java.util.ArrayList;
import java.util.List;
import javax.swing.text.JTextComponent;
import jsyntaxpane.actions.ActionUtils;
import jsyntaxpane.components.Markers;
import newcrunch.util.DisplayHelper;
import newcrunch.util.PropertyLoader;

/**
 * Class to store highlight positions and to set the highlights
 * in the editor pane when called upon to do so.
 * @author WL
 */
public class KeyHighlighter 
{
    private List<Integer> startPositions;
    private List<Integer> stopPositions;
    private List<Integer> auxStartPositions;
    private List<Integer> auxStopPositions;
    private static Color highlightColor = Color.ORANGE;
    private static Color focusHighlightColor = Color.YELLOW;
    private Markers.SimpleMarker marker;
    private Markers.SimpleMarker focusMarker;
    private JTextComponent editor;
    
    public KeyHighlighter(JTextComponent editor)
    {
        startPositions = new ArrayList<Integer>();
        stopPositions = new ArrayList<Integer>();
        
        auxStartPositions = new ArrayList<Integer>();
        auxStopPositions = new ArrayList<Integer>();
        
        marker = new Markers.SimpleMarker(highlightColor);
        focusMarker = new Markers.SimpleMarker(focusHighlightColor);
        
        this.editor = editor;
    }
    
    /**
     * Adds the start and stop position of keyword
     * to highlight in the editor
     * @param start
     * @param stop 
     */
    public void addPosition(int start, int stop)
    {
        startPositions.add(start);
        stopPositions.add(stop);
    }
    
    /**
     * Same as @addPosition, the only difference
     * is that this set of positions
     * will not be used in changing the caret's
     * position.
     * @param start
     * @param stop 
     */
    public void addAuxPosition(int start, int stop)
    {
        auxStartPositions.add(start);
        auxStopPositions.add(stop);
    }
    
    /**
     * Makes the associated editor focus at
     * the highlight located at index.
     * @param index 
     */
    public void jumpToHighlight(int index)
    {
        updateHighlights(index);
        
        int start = getStartPosition(index);
        int end = getStopPosition(index);
        editor.setCaretPosition(start);
        DisplayHelper.centerLineInScrollPane(editor);
        
        Markers.removeMarkers(editor, focusMarker);
        Markers.markText(editor, start, end, focusMarker);
    }
    
    /**
     * Returns the start position of the keyword
     * being highlighted
     * @param index - the index of the keyword highlighted, starting from 0.
     * @return 
     */
    public int getStartPosition(int index)
    {
        return startPositions.get(index);
    }
    
    /**
     * Returns the stop position of the keyword
     * being highlighted
     * @param index - the index of the keyword highlighted, starting from 0.
     * @return 
     */
    public int getStopPosition(int index)
    {
        return stopPositions.get(index);
    }
    
    /**
     * Removes the previous highlighting and 
     * adds the highlights for the current
     * set of keywords.
     * @param exception 
     */
    public void updateHighlights(int exception)
    {
        removeHighlights();
        
        for (int i = 0; i < startPositions.size(); i++)
            if (i != exception)
                Markers.markText(editor, startPositions.get(i), stopPositions.get(i), marker);
        
        for (int i = 0; i < auxStartPositions.size(); i++)
            Markers.markText(editor, auxStartPositions.get(i), auxStopPositions.get(i), marker);
    }
    
    /**
     * Removes the previous highlighting and
     * adds the highlights for the current
     * set of keywords
     */
    public void updateHighlights()
    {
        updateHighlights(-1);
    }
    
    /**
     * Removes all highlighting done by
     * the previous KeyHighlighter
     */
    public void removeHighlights()
    {
        Markers.removeMarkers(editor, marker);
        Markers.removeMarkers(editor, focusMarker);
    }
    
    /**
     * Add highlighting from start position (inclusive) to stop position (exclusive).
     * @param highlighter
     * @param editor
     * @param text
     * @param start
     * @param stop 
     */
    public static void addKeyHighlightPos(KeyHighlighter highlighter, 
            int start, int stop)
    {
        highlighter.addPosition(start, stop);
    }
    
    /**
     * Adds the highlight that will not be used to change
     * the caret's position.
     * @param highlighter
     * @param start
     * @param stop 
     */
    public static void addAuxHighlight(KeyHighlighter highlighter, 
            int start, int stop)
    {
        highlighter.addAuxPosition(start, stop);
    }
    
    /**
     * Adds a highlight position in the given highlighter object.
     * @param highlighter
     * @param editor
     * @param text
     * @param line
     * @param column 
     */
    public static void addKeyHighlight(KeyHighlighter highlighter, 
            JTextComponent editor, String text, int line, int column)
    {
        int start = ActionUtils.getDocumentPosition(editor, line, column);
        int stop = text.length() + start;

        highlighter.addPosition(start, stop);
    }
    
    static 
    {
        highlightColor = PropertyLoader.getColorProperty("keywordhighlight");
        focusHighlightColor = PropertyLoader.getColorProperty("keywordfocus");
    }
}
